package com.quanyan.weichat.util;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContexts;

import javax.net.ssl.SSLContext;
import java.io.InputStream;
import java.net.SocketTimeoutException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;

/**
 * Created by zhuo.shi on 2016/7/5.
 */
public class HttpClientUtil4Weichat {

    private InputStream sslCertificate; //微信商户证书

    private String sslKeyStore;         //微信商户证书密码，默认为mchid

    private InputStream getSslCertificate() {
        return sslCertificate;
    }

    public void setSslCertificate(InputStream sslCertificate) {
        this.sslCertificate = sslCertificate;
    }

    private String getSslKeyStore() {
        return sslKeyStore;
    }

    public void setSslKeyStore(String sslKeyStore) {
        this.sslKeyStore = sslKeyStore;
    }

    public String postXml2Wx(String url, String body)throws Exception{
        HttpPost post = new HttpPost(url);
        if (StringUtils.isNotBlank(body)) {
            post.addHeader("Connection", "keep-alive");
            post.addHeader("Accept", "*/*");
            post.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
            post.addHeader("X-Requested-With", "XMLHttpRequest");
            post.addHeader("Host", "api.mch.weixin.qq.com");
            post.addHeader("Cache-Control", "max-age=0");
            HttpEntity entity = new StringEntity(body, ContentType.create("application/x-www-form-urlencoded", Consts.UTF_8));
            post.setEntity(entity);
        }
        return post(post, 5000, 3000);
    }

    /**
     * 发送一个 Post 请求, 使用指定的字符集编码.
     *
     * @param post
     * @param connTimeout 建立链接超时时间,毫秒.
     * @param readTimeout 响应超时时间,毫秒.
     * @return ResponseBody, 使用指定的字符集编码.
     * @throws ConnectTimeoutException 建立链接超时异常
     * @throws SocketTimeoutException  响应超时
     * @throws Exception
     */
    private String post(HttpPost post, Integer connTimeout, Integer readTimeout)
            throws Exception {
        HttpClient client = null;
        String result = "";
        try {
            // 设置参数
            RequestConfig.Builder customReqConf = RequestConfig.custom();
            if (connTimeout != null) {
                customReqConf.setConnectTimeout(connTimeout);
            }
            if (readTimeout != null) {
                customReqConf.setSocketTimeout(readTimeout);
            }
            post.setConfig(customReqConf.build());

            HttpResponse res;
            if (post.getURI().toString().startsWith("https")) {
                // 执行 Https 请求.
                client = createSSLInsecureClient();
                res = client.execute(post);
            } else {
                // 执行 Http 请求.
                PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
                cm.setMaxTotal(128);
                cm.setDefaultMaxPerRoute(128);
                client = HttpClients.custom().setConnectionManager(cm).build();
                res = client.execute(post);
            }
            result = IOUtils.toString(res.getEntity().getContent(), Consts.UTF_8.toString());
        } finally {
            post.releaseConnection();
            if (post.getURI().toString().startsWith("https") && client != null
                    && client instanceof CloseableHttpClient) {
                ((CloseableHttpClient) client).close();
            }
        }
        return result;
    }

    private CloseableHttpClient createSSLInsecureClient() throws GeneralSecurityException {
        /**2016-06-23 zhuo.shi 生成sslconnection方法，适用引入微信商户证书*/
        CloseableHttpClient client = HttpClients.createDefault();
        try {
            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            InputStream instream = this.getSslCertificate();
            try {
                //指定PKCS12的密码(商户ID)
                keyStore.load(instream, this.getSslKeyStore().toCharArray());
            } finally {
                instream.close();
            }
            SSLContext sslcontext = SSLContexts.custom()
                    .loadKeyMaterial(keyStore, this.getSslKeyStore().toCharArray()).build();
            //指定TLS版本
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                    sslcontext,new String[] { "TLSv1" }, null,
                    SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); //设置httpclient的SSLSocketFactory
            client = HttpClients.custom()
                    .setSSLSocketFactory(sslsf)
                    .build();

        } catch (Exception e) {
            e.printStackTrace();
        }
        return client;
    }
}
